package com.soyorin.shop.service;

import com.soyorin.shop.entity.Shop;
import com.soyorin.shop.mapper.ShopMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商铺统计服务
 * 展示可扩展性的实现示例
 * 
 * @author soyorin
 * @version 1.0
 * @since 2024-01-01
 */
@Slf4j
@Service
public class ShopStatisticsService {

    @Autowired
    private ShopMapper shopMapper;

    @Autowired
    private ShopService shopService;

    /**
     * 获取商铺统计信息
     * 
     * @param shopId 商铺ID
     * @return 商铺统计信息
     */
    @Cacheable(value = "shopStatistics", key = "#shopId")
    public ShopStatistics getShopStatistics(Long shopId) {
        log.info("获取商铺统计信息, shopId: {}", shopId);
        
        Shop shop = shopService.getById(shopId);
        if (shop == null) {
            log.warn("商铺不存在, shopId: {}", shopId);
            return null;
        }

        ShopStatistics statistics = new ShopStatistics();
        statistics.setShopId(shopId);
        statistics.setShopName(shop.getName());
        statistics.setAverageRating(shop.getAvRating());
        statistics.setAverageAmount(shop.getAvAmount());
        statistics.setMonthlyOrderCount(shop.getMonthlyOrderCount());
        statistics.setDeliveryFee(shop.getDeliveryFee());
        statistics.setMinOrderAmount(shop.getMinOrderAmount());

        // 计算营业状态
        statistics.setOpenStatus(isShopOpen(shop));
        
        // 计算距离用户中心的平均距离（这里假设用户中心为北京天安门）
        double userCenterX = 116.3974;
        double userCenterY = 39.9093;
        double distance = calculateDistance(userCenterX, userCenterY, shop.getPositionX(), shop.getPositionY());
        statistics.setDistanceFromCenter(distance);

        log.info("商铺统计信息获取成功, shopId: {}, name: {}", shopId, shop.getName());
        return statistics;
    }

    /**
     * 更新商铺月订单量
     * 
     * @param shopId 商铺ID
     * @param newOrderCount 新的订单量
     */
    public void updateMonthlyOrderCount(Long shopId, Integer newOrderCount) {
        log.info("更新商铺月订单量, shopId: {}, newOrderCount: {}", shopId, newOrderCount);
        
        Shop shop = shopService.getById(shopId);
        if (shop == null) {
            log.warn("商铺不存在, shopId: {}", shopId);
            return;
        }

        shop.setMonthlyOrderCount(newOrderCount);
        boolean updateResult = shopService.updateById(shop);
        
        if (updateResult) {
            log.info("商铺月订单量更新成功, shopId: {}, newOrderCount: {}", shopId, newOrderCount);
        } else {
            log.error("商铺月订单量更新失败, shopId: {}", shopId);
        }
    }

    /**
     * 更新商铺平均评分
     * 
     * @param shopId 商铺ID
     * @param newRating 新的评分
     */
    public void updateAverageRating(Long shopId, Double newRating) {
        log.info("更新商铺平均评分, shopId: {}, newRating: {}", shopId, newRating);
        
        if (newRating < 0 || newRating > 5) {
            log.warn("评分无效, shopId: {}, newRating: {}", shopId, newRating);
            return;
        }

        Shop shop = shopService.getById(shopId);
        if (shop == null) {
            log.warn("商铺不存在, shopId: {}", shopId);
            return;
        }

        shop.setAvRating(newRating);
        boolean updateResult = shopService.updateById(shop);
        
        if (updateResult) {
            log.info("商铺平均评分更新成功, shopId: {}, newRating: {}", shopId, newRating);
        } else {
            log.error("商铺平均评分更新失败, shopId: {}", shopId);
        }
    }

    /**
     * 获取所有商铺的统计概览
     * 
     * @return 统计概览
     */
    @Cacheable(value = "shopStatisticsOverview")
    public ShopStatisticsOverview getShopStatisticsOverview() {
        log.info("获取所有商铺统计概览");
        
        List<Shop> allShops = shopService.list();
        
        ShopStatisticsOverview overview = new ShopStatisticsOverview();
        overview.setTotalShops(allShops.size());
        
        // 计算平均评分
        double avgRating = allShops.stream()
                .mapToDouble(shop -> shop.getAvRating() != null ? shop.getAvRating() : 0.0)
                .average()
                .orElse(0.0);
        overview.setAverageRating(avgRating);
        
        // 计算平均消费
        double avgAmount = allShops.stream()
                .mapToDouble(shop -> shop.getAvAmount() != null ? shop.getAvAmount() : 0.0)
                .average()
                .orElse(0.0);
        overview.setAverageAmount(avgAmount);
        
        // 计算总订单量
        int totalOrders = allShops.stream()
                .mapToInt(shop -> shop.getMonthlyOrderCount() != null ? shop.getMonthlyOrderCount() : 0)
                .sum();
        overview.setTotalMonthlyOrders(totalOrders);
        
        // 统计营业状态
        long openShops = allShops.stream()
                .filter(this::isShopOpen)
                .count();
        overview.setOpenShops((int) openShops);
        overview.setClosedShops(allShops.size() - (int) openShops);
        
        log.info("商铺统计概览获取成功, 总商铺数: {}, 营业中: {}, 平均评分: {}", 
                overview.getTotalShops(), overview.getOpenShops(), overview.getAverageRating());
        
        return overview;
    }

    /**
     * 获取按评分分组的商铺统计
     * 
     * @return 按评分分组的统计
     */
    public Map<String, Long> getShopCountByRating() {
        log.info("获取按评分分组的商铺统计");
        
        List<Shop> allShops = shopService.list();
        
        Map<String, Long> ratingGroups = allShops.stream()
                .collect(Collectors.groupingBy(shop -> {
                    Double rating = shop.getAvRating();
                    if (rating == null) return "无评分";
                    if (rating >= 4.5) return "4.5分以上";
                    if (rating >= 4.0) return "4.0-4.5分";
                    if (rating >= 3.5) return "3.5-4.0分";
                    if (rating >= 3.0) return "3.0-3.5分";
                    return "3.0分以下";
                }, Collectors.counting()));
        
        log.info("按评分分组统计完成: {}", ratingGroups);
        return ratingGroups;
    }

    /**
     * 检查商铺是否营业
     * 
     * @param shop 商铺信息
     * @return 是否营业
     */
    private boolean isShopOpen(Shop shop) {
        if (shop.getStartTime() == null || shop.getEndTime() == null) {
            return false;
        }
        
        java.time.LocalTime now = java.time.LocalTime.now();
        return !now.isBefore(shop.getStartTime()) && !now.isAfter(shop.getEndTime());
    }

    /**
     * 计算两点间距离（使用欧几里得距离）
     * 
     * @param x1 点1的x坐标
     * @param y1 点1的y坐标
     * @param x2 点2的x坐标
     * @param y2 点2的y坐标
     * @return 距离
     */
    private double calculateDistance(double x1, double y1, double x2, double y2) {
        return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
    }

    /**
     * 商铺统计信息
     */
    public static class ShopStatistics {
        private Long shopId;
        private String shopName;
        private Double averageRating;
        private Integer averageAmount;
        private Integer monthlyOrderCount;
        private Integer deliveryFee;
        private Integer minOrderAmount;
        private boolean openStatus;
        private double distanceFromCenter;

        // Getters and Setters
        public Long getShopId() { return shopId; }
        public void setShopId(Long shopId) { this.shopId = shopId; }
        
        public String getShopName() { return shopName; }
        public void setShopName(String shopName) { this.shopName = shopName; }
        
        public Double getAverageRating() { return averageRating; }
        public void setAverageRating(Double averageRating) { this.averageRating = averageRating; }
        
        public Integer getAverageAmount() { return averageAmount; }
        public void setAverageAmount(Integer averageAmount) { this.averageAmount = averageAmount; }
        
        public Integer getMonthlyOrderCount() { return monthlyOrderCount; }
        public void setMonthlyOrderCount(Integer monthlyOrderCount) { this.monthlyOrderCount = monthlyOrderCount; }
        
        public Integer getDeliveryFee() { return deliveryFee; }
        public void setDeliveryFee(Integer deliveryFee) { this.deliveryFee = deliveryFee; }
        
        public Integer getMinOrderAmount() { return minOrderAmount; }
        public void setMinOrderAmount(Integer minOrderAmount) { this.minOrderAmount = minOrderAmount; }
        
        public boolean isOpenStatus() { return openStatus; }
        public void setOpenStatus(boolean openStatus) { this.openStatus = openStatus; }
        
        public double getDistanceFromCenter() { return distanceFromCenter; }
        public void setDistanceFromCenter(double distanceFromCenter) { this.distanceFromCenter = distanceFromCenter; }
    }

    /**
     * 商铺统计概览
     */
    public static class ShopStatisticsOverview {
        private int totalShops;
        private double averageRating;
        private double averageAmount;
        private int totalMonthlyOrders;
        private int openShops;
        private int closedShops;

        // Getters and Setters
        public int getTotalShops() { return totalShops; }
        public void setTotalShops(int totalShops) { this.totalShops = totalShops; }
        
        public double getAverageRating() { return averageRating; }
        public void setAverageRating(double averageRating) { this.averageRating = averageRating; }
        
        public double getAverageAmount() { return averageAmount; }
        public void setAverageAmount(double averageAmount) { this.averageAmount = averageAmount; }
        
        public int getTotalMonthlyOrders() { return totalMonthlyOrders; }
        public void setTotalMonthlyOrders(int totalMonthlyOrders) { this.totalMonthlyOrders = totalMonthlyOrders; }
        
        public int getOpenShops() { return openShops; }
        public void setOpenShops(int openShops) { this.openShops = openShops; }
        
        public int getClosedShops() { return closedShops; }
        public void setClosedShops(int closedShops) { this.closedShops = closedShops; }
    }
}
